package com.piper.lock;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import redis.clients.jedis.Jedis;

import java.util.Collections;
import java.util.Date;
import java.util.concurrent.*;

/**
 * 看门狗：定时续约
 */
public class Watchdog {

    /**
     * 定时任务线程池
     */
    private static final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(10, new WatchdogThreadFactory());

    /**
     * 看门狗lua脚本
     */
    private static final String WATCHDOG_SCRIPT =
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                    "return redis.call('expire', KEYS[1], ARGV[2]); " +
                    "else return 0; " +
                    "end;";

    /**
     * 启动看门狗
     *
     * @param jedis
     * @param key
     * @param value
     * @param second
     * @return
     */
    public static boolean startWatchdog(Jedis jedis, String key, String value, long second) {
        long period = second / 30;
        try {
            executorService.scheduleAtFixedRate(() -> renewExpire(jedis, key, value, second), period, period, TimeUnit.SECONDS);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 启动看门狗
     *
     * @param stringRedisTemplate
     * @param key
     * @param value
     * @param second
     * @return
     */
    public static boolean startWatchdog(StringRedisTemplate stringRedisTemplate, String key, String value, long second) {
        long period = second / 30;
        try {
            executorService.scheduleAtFixedRate(() -> renewExpire(stringRedisTemplate, key, value, second), period, period, TimeUnit.SECONDS);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 续约脚本
     *
     * @param jedis
     * @param key
     * @param value
     * @param second
     */
    private static void renewExpire(Jedis jedis, String key, String value, long second) {
        Object result = jedis.eval(WATCHDOG_SCRIPT, 1, key, value, String.valueOf(second));
        System.out.println(String.format("执行watchdog->>> key:%s, value:%s, result:%s, time:%tT", key, value, result, new Date()));
    }

    /**
     * 续约脚本
     *
     * @param stringRedisTemplate
     * @param key
     * @param value
     * @param second
     */
    private static void renewExpire(StringRedisTemplate stringRedisTemplate, String key, String value, long second) {
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(WATCHDOG_SCRIPT, Boolean.class);
        Boolean result = stringRedisTemplate.execute(redisScript, Collections.singletonList(key), value, String.valueOf(second));
        System.out.println(String.format("执行watchdog->>> key:%s, value:%s, result:%s, time:%tT", key, value, result, new Date()));
    }

}
